﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Windows.Input;
using DataStore;
using DataStore.Domain;
using DataStore.Repositories;
using Infrastructure.CurrentData;
using Microsoft.Practices.Composite.Events;

namespace Infrastructure.ViewModels
{
    /// <summary>
    /// Book viewmodel
    /// </summary>
    public class BookViewModel : CatalogItemViewModel
    {
        /// <summary>
        /// The current Book
        /// </summary>
        Book _book;

        /// <summary>
        /// Initializes a new instance of the <see cref="BookViewModel"/> class.
        /// </summary>
        /// <param name="book">The book.</param>
        public BookViewModel(Book book) : base(book)
        {
            Initialize(book);
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CatalogItemViewModel"/> class.
        /// </summary>
        /// <param name="eventAggregator">The event aggregator.</param>
        /// <param name="book">The book.</param>
        public BookViewModel(IEventAggregator eventAggregator, Book book)
            : base(eventAggregator, book)
        {
            Initialize(book);
        }

        /// <summary>
        /// Initializes the specified book.
        /// </summary>
        /// <param name="book">The book.</param>
        void Initialize(Book book)
        {
            _book = book;
            State = ModelState.Active;


            InitAuthors(book);
            InitCovers(book);
            InitLinks(book);
        }

        /// <summary>
        /// Initializes the links.
        /// </summary>
        /// <param name="book">The book.</param>
        void InitLinks(Book book)
        {
            if (book.Links != null)
            {
                foreach (var link in book.Links)
                {
                    _links.Add(new LinkViewModel(EventAggregator, link));
                }
            }

            _links.CollectionChanged += (sender, e) =>
                                            {
                                                switch (e.Action)
                                                {
                                                    case NotifyCollectionChangedAction.Add:
                                                        foreach (LinkViewModel item in e.NewItems)
                                                        {
                                                            if (_book.Links == null)
                                                            {
                                                                _book.Links = new List<Link>();
                                                            }
                                                            _book.Links.Add(item.Link);
                                                            OnPropertyChanged("Links");
                                                        }
                                                        break;
                                                    case NotifyCollectionChangedAction.Remove:
                                                        foreach (LinkViewModel item in e.NewItems)
                                                        {
                                                            if (_book.Links != null && _book.Links.Count > 0)
                                                            {
                                                                _book.Links.Remove(item.Link);
                                                                OnPropertyChanged("Links");
                                                            }
                                                        }
                                                        break;
                                                    case NotifyCollectionChangedAction.Replace:
                                                        throw new NotSupportedException("Replace operation not supported");
                                                        break;
                                                    case NotifyCollectionChangedAction.Move:
                                                        throw new NotSupportedException("Move operation not supported");
                                                        break;
                                                    case NotifyCollectionChangedAction.Reset:
                                                        throw new NotSupportedException("Reset operation not supported");
                                                        break;
                                                    default:
                                                        throw new InvalidOperationException();
                                                        break;

                                                }
                                            };
        }

        /// <summary>
        /// Initializes the covers.
        /// </summary>
        /// <param name="book">The book.</param>
        void InitCovers(Book book)
        {
            if(book.Cover != null)
            {
                foreach (var cover in book.Cover)
                {
                    _covers.Add(new CoverViewModel(EventAggregator, cover));
                }
            }

            _covers.CollectionChanged += (sender, e) =>
                                             {
                                                 switch (e.Action)
                                                 {
                                                     case NotifyCollectionChangedAction.Add:
                                                         foreach (CoverViewModel item in e.NewItems)
                                                         {
                                                             if (_book.Cover == null)
                                                             {
                                                                 _book.Cover = new List<Cover>();
                                                             }
                                                             _book.Cover.Add(item.Cover);
                                                             // TODO refine property changed event: filter for type
                                                             OnPropertyChanged("Cover");
                                                             OnPropertyChanged("FrontCovers");
                                                             OnPropertyChanged("BackCovers");
                                                         }
                                                         break;
                                                     case NotifyCollectionChangedAction.Remove:
                                                         foreach (CoverViewModel item in e.NewItems)
                                                         {
                                                             if (_book.Cover != null && _book.Cover.Count > 0)
                                                             {
                                                                 _book.Cover.Remove(item.Cover);
                                                                 OnPropertyChanged("Cover");
                                                                 // TODO refine property changed event: filter for type
                                                                 OnPropertyChanged("FrontCovers");
                                                                 OnPropertyChanged("BackCovers");
                                                             }
                                                         }
                                                         break;
                                                     case NotifyCollectionChangedAction.Replace:
                                                         throw new NotSupportedException("Replace operation not supported");
                                                         break;
                                                     case NotifyCollectionChangedAction.Move:
                                                         throw new NotSupportedException("Move operation not supported");
                                                         break;
                                                     case NotifyCollectionChangedAction.Reset:
                                                         throw new NotSupportedException("Reset operation not supported");
                                                         break;
                                                     default:
                                                         throw new InvalidOperationException();
                                                         break;

                                                 }
                                             };
        }

        // TODO pull up functionality to base class
        /// <summary>
        /// Inits the authors.
        /// Propagates Add, Remove operations to book entity's author collection
        /// </summary>
        /// <param name="book">The book.</param>
        /// <exception cref="NotSupportedException">Replace, move, reset operation not supported</exception>
        /// <exception cref="InvalidOperationException"><c>InvalidOperationException</c>.</exception>
        void InitAuthors(Book book)
        {
            if (book.Authors != null)
            {
                foreach (var author in book.Authors)
                {
                    _authors.Add(new AuthorViewModel(EventAggregator, author));
                }
            }
            _authors.CollectionChanged += ((sender, e) =>
                                               {
                                                   switch (e.Action)
                                                   {
                                                       case NotifyCollectionChangedAction.Add:
                                                           foreach (AuthorViewModel item in e.NewItems)
                                                           {
                                                               if(_book.Authors == null)
                                                               {
                                                                   _book.Authors = new List<Author>();
                                                               }
                                                               _book.Authors.Add(item.Author);
                                                               OnPropertyChanged("Authors");
                                                           }
                                                           break;
                                                       case NotifyCollectionChangedAction.Remove:
                                                           foreach (AuthorViewModel item in e.NewItems)
                                                           {
                                                               if (_book.Authors != null && _book.Authors.Count > 0)
                                                               {
                                                                   _book.Authors.Remove(item.Author);
                                                                   OnPropertyChanged("Authors");
                                                               }
                                                           }
                                                           break;
                                                       case NotifyCollectionChangedAction.Replace:
                                                           throw new NotSupportedException("Replace operation not supported");
                                                           break;
                                                       case NotifyCollectionChangedAction.Move:
                                                           throw new NotSupportedException("Move operation not supported");
                                                           break;
                                                       case NotifyCollectionChangedAction.Reset:
                                                           throw new NotSupportedException("Reset operation not supported");
                                                           break;
                                                       default:
                                                           throw new InvalidOperationException();
                                                           break;

                                                   }
                                               });
        }

        /// <summary>
        /// Gets the Book entity.
        /// </summary>
        /// <value>The Book entity.</value>
        public Book Book { get { return _book; } }

        /// <summary>
        /// Gets or sets the id.
        /// </summary>
        /// <value>The id.</value>
        public override Guid Id
        {
            get
            {
                return _book.Id;
            }
            set
            {
                if (_book.Id != value)
                {
                    _book.Id = value;
                    OnPropertyChanged("Id");
                }
            }
        }
        /// <summary>
        /// Gets or sets the document type.
        /// </summary>
        /// <value>The type.</value>
        public override DocumentType Type
        {
            get
            {
                return _book.Type;
            }
            set
            {
                if (_book.Type != value)
                {
                    _book.Type = value;
                    OnPropertyChanged("Type");
                }
            }
        }

        readonly ObservableCollection<AuthorViewModel> _authors = new ObservableCollection<AuthorViewModel>();
        /// <summary>
        /// The name(s) of the author(s).
        /// </summary>
        /// <value>The author.</value>
        public override IList<AuthorViewModel> Authors
        {
            get
            {
                return _authors;
            }
        }

        /// <summary>
        /// Name(s) of editor(s). If there is also an author field, then the editor field gives 
        /// the editor of the book or collection in which the reference appears.
        /// </summary>
        /// <value>The editor.</value>
        public override ICollection<Editor> Editors
        {
            get
            {
                return _book.Editors;
            }
            set
            {
                _book.Editors = value;
                OnPropertyChanged("Editors");
            }
        }
        /// <summary>
        /// A chapter (or section or whatever) number.
        /// </summary>
        /// <value>The chapter.</value>
        public override string Chapter
        {
            get
            {
                return _book.Chapter;
            }
            set
            {
                if (_book.Chapter != value)
                {
                    _book.Chapter = value;
                    OnPropertyChanged("Chapter");
                }
            }
        }
        /// <summary>
        /// The edition of a book - for example, "Second". 
        /// This should be an ordinal, and should have the first letter capitalized, as shown here; 
        /// the standard styles convert to lower case when necessary.
        /// </summary>
        /// <value>The edition.</value>
        public override string Edition
        {
            get
            {
                return _book.Edition;
            }
            set
            {
                if (_book.Edition != value)
                {
                    _book.Edition = value;
                    OnPropertyChanged("Edition");
                }
            }
        }
        /// <summary>
        /// How something strange has been published. The first word should be capitalized.
        /// </summary>
        /// <value>The how published.</value>
        public override string HowPublished
        {
            get
            {
                return _book.HowPublished;
            }
            set
            {
                if (_book.HowPublished != value)
                {
                    _book.HowPublished = value;
                    OnPropertyChanged("HowPublished");
                }
            }
        }
        /// <summary>
        /// The sponsoring institution of a technical report.
        /// </summary>
        /// <value>The institution.</value>
        public override ICollection<Company> Sponsors
        {
            get
            {
                return _book.Sponsors;
            }
            set
            {
                _book.Sponsors = value;
                OnPropertyChanged("Sponsors");
            }
        }
        /// <summary>
        /// Gets or sets the date written.
        /// </summary>
        /// <value>The date written.</value>
        public override DateTime? DateWritten
        {
            get
            {
                return _book.DateWritten;
            }
            set
            {
                if (_book.DateWritten != value)
                {
                    _book.DateWritten = value;
                    OnPropertyChanged("DateWritten");
                }
            }
        }
        /// <summary>
        /// Gets or sets the date published.
        /// </summary>
        /// <value>The date published.</value>
        public override DateTime? DatePublished
        {
            get
            {
                return _book.DatePublished;
            }
            set
            {
                if (_book.DatePublished != value)
                {
                    _book.DatePublished = value;
                    OnPropertyChanged("DatePublished");
                }
            }
        }
        /// <summary>
        /// Gets or sets the comments.
        /// </summary>
        /// <value>The comments.</value>
        public override string Comment
        {
            get
            {
                return _book.Comment;
            }
            set
            {
                if (_book.Comment != value)
                {
                    _book.Comment = value;
                    OnPropertyChanged("Comment");
                }
            }
        }
        /// <summary>
        /// One or more page numbers or range of numbers.
        /// </summary>
        /// <value>The pages.</value>
        public override ICollection<Range> Pages
        {
            get
            {
                return _book.Pages;
            }
            set
            {
                _book.Pages = value;
                OnPropertyChanged("Pages");
            }
        }
        /// <summary>
        /// The publisher's name.
        /// </summary>
        /// <value>The publisher.</value>
        public override Company Publisher
        {
            get
            {
                return _book.Publisher;
            }
            set
            {
                if (_book.Publisher != value)
                {
                    _book.Publisher = value;
                    OnPropertyChanged("Publisher");
                }
            }
        }
        /// <summary>
        /// The name of a series or set of books.
        /// </summary>
        /// <value>The series.</value>
        public override string Series
        {
            get
            {
                return _book.Series;
            }
            set
            {
                if (_book.Series != value)
                {
                    _book.Series = value;
                    OnPropertyChanged("Series");
                }
            }
        }
        /// <summary>
        /// The work's title.
        /// </summary>
        /// <value>The title.</value>
        public override string Title
        {
            get
            {
                return _book.Title;
            }
            set
            {
                if (_book.Title != value)
                {
                    _book.Title = value;
                    OnPropertyChanged("Title");
                }
            }
        }
        /// <summary>
        /// The type of a technical report - for example, "Research Note".
        /// </summary>
        /// <value>The type of the report.</value>
        public override string ReportType
        { 
            get
            {
                return _book.ReportType;
            }
            set
            {
                if (_book.ReportType != value)
                {
                    _book.ReportType = value;
                    OnPropertyChanged("ReportType");
                }
            }
        }
        /// <summary>
        /// The volume of a journal or multi-volume book.
        /// </summary>
        /// <value>The volume.</value>
        public override string Volume 
        { 
            get
            {
                return _book.Volume;
            }
            set
            {
                if (_book.Volume != value)
                {
                    _book.Volume = value;
                    OnPropertyChanged("Volume");
                }
            }
        }

        readonly ObservableCollection<LinkViewModel> _links = new ObservableCollection<LinkViewModel>();
        /// <summary>
        /// Gets or sets the links of the document.
        /// </summary>
        /// <value>The link.</value>
        public override IList<LinkViewModel> Links
        {
            get
            {
                return _links;
            }
        }
        /// <summary>
        /// Gets or sets the country of publication.
        /// </summary>
        /// <value>The country.</value>
        public override Country Country
        {
            get
            {
                return _book.Country;
            }
            set
            {
                if (_book.Country != value)
                {
                    _book.Country = value;
                    OnPropertyChanged("Country");
                }
            }
        }
        /// <summary>
        /// Gets or sets the language of the document.
        /// </summary>
        /// <value>The language.</value>
        public override Language Language
        {
            get
            {
                return _book.Language;
            }
            set
            {
                if (_book.Language != value)
                {
                    _book.Language = value;
                    OnPropertyChanged("Language");
                }
            }
        }
        /// <summary>
        /// Gets or sets the width of the document.
        /// </summary>
        /// <value>The width.</value>
        public override float? Width
        {
            get
            {
                return _book.Width;
            }
            set
            {
                if (_book.Width != value)
                {
                    _book.Width = value;
                    OnPropertyChanged("Width");
                }
            }
        }
        /// <summary>
        /// Gets or sets the height of the document.
        /// </summary>
        /// <value>The height.</value>
        public override float? Height
        {
            get
            {
                return _book.Height;
            }
            set
            {
                if (_book.Height != value)
                {
                    _book.Height = value;
                    OnPropertyChanged("Height");
                }
            }
        }

        readonly ObservableCollection<CoverViewModel> _covers = new ObservableCollection<CoverViewModel>();
        /// <summary>
        /// Gets or sets the cover.
        /// </summary>
        /// <value>The cover.</value>
        public override IList<CoverViewModel> Cover
        {
            get
            {
                return _covers;
            }
        }

        /// <summary>
        /// Gets the front covers.
        /// </summary>
        /// <value>The front covers.</value>
        public override IEnumerable<CoverViewModel> FrontCovers
        {
            get
            {
                VerifyCalledOnUIThread();
                var covers = from c in _covers
                             where c.Type == CoverType.Front
                             select c;
                return covers;
            }
        }

        /// <summary>
        /// Gets the back covers.
        /// </summary>
        /// <value>The back covers.</value>
        public override IEnumerable<CoverViewModel> BackCovers
        {
            get
            {
                VerifyCalledOnUIThread();
                var covers = from c in _covers
                             where c.Type == CoverType.Back
                             select c;
                return covers;
            }
        }

        /// <summary>
        /// Gets or sets the number of pages.
        /// </summary>
        /// <value>The number of pages.</value>
        public override int? NumberOfPages
        {
            get
            {
                return _book.NumberOfPages;
            }
            set
            {
                if (_book.NumberOfPages != value)
                {
                    _book.NumberOfPages = value;
                    OnPropertyChanged("NumberOfPages");
                }
            }
        }
        /// <summary>
        /// Gets or sets the publishing format of the document.
        /// </summary>
        /// <value>The format.</value>
        public override PublishingFormat Format
        {
            get
            {
                return _book.Format;
            }
            set
            {
                if (_book.Format != value)
                {
                    _book.Format = value;
                    OnPropertyChanged("Format");
                }
            }
        }
        /// <summary>
        /// Gets or sets the citations found in the document.
        /// </summary>
        /// <value>The citations.</value>
        public override ICollection<CatalogItem> Citations
        {
            get
            {
                return _book.Citations;
            }
            set
            {
                _book.Citations = value;
                OnPropertyChanged("Citations");
            }
        }
        /// <summary>
        /// Gets or sets the keywords.
        /// </summary>
        /// <value>The keywords.</value>
        public override ICollection<Keyword> Keywords 
        { 
            get
            {
                return _book.Keywords;   
            }
            set
            {
                _book.Keywords = value;
                OnPropertyChanged("Keywords");
            }
        }
        /// <summary>
        /// Gets or sets the categories.
        /// </summary>
        /// <value>The categories.</value>
        public override ICollection<Category> Categories
        {
            get
            {
                return _book.Categories;
            }
            set
            {
                _book.Categories = value;
                OnPropertyChanged("Categories");
            }
        }
        /// <summary>
        /// Gets or sets the contents.
        /// </summary>
        /// <value>The contents.</value>
        public override string Contents
        {
            get
            {
                return _book.Contents;
            }
            set
            {
                if (_book.Contents != value)
                {
                    _book.Contents = value;
                    OnPropertyChanged("Contents");
                }
            }
        }
        /// <summary>
        /// Gets or sets the owner of the document.
        /// </summary>
        /// <value>The owner.</value>
        public override Person Owner
        {
            get
            {
                return _book.Owner;
            }
            set
            {
                if (_book.Owner != value)
                {
                    _book.Owner = value;
                    OnPropertyChanged("Owner");
                }
            }
        }
        /// <summary>
        /// Gets or sets the purchase date.
        /// </summary>
        /// <value>The purchase date.</value>
        public override DateTime? PurchaseDate
        {
            get
            {
                return _book.PurchaseDate;
            }
            set
            {
                if (_book.PurchaseDate != value)
                {
                    _book.PurchaseDate = value;
                    OnPropertyChanged("PurchaseDate");
                }
            }
        }
        /// <summary>
        /// Gets or sets the purchase store.
        /// </summary>
        /// <value>The purchase store.</value>
        public override Company PurchaseStore
        {
            get
            {
                return _book.PurchaseStore;
            }
            set
            {
                if (_book.PurchaseStore != value)
                {
                    _book.PurchaseStore = value;
                    OnPropertyChanged("PurchaseStore");
                }
            }
        }
        /// <summary>
        /// Gets or sets the purchase price.
        /// </summary>
        /// <value>The purchase price.</value>
        public override float? PurchasePrice
        {
            get
            {
                return _book.PurchasePrice;
            }
            set
            {
                if (_book.PurchasePrice != value)
                {
                    _book.PurchasePrice = value;
                    OnPropertyChanged("PurchasePrice");
                }
            }
        }
        /// <summary>
        /// Gets or sets the current price.
        /// </summary>
        /// <value>The current price.</value>
        public override float? CurrentPrice
        {
            get
            {
                return _book.CurrentPrice;
            }
            set
            {
                if(_book.CurrentPrice != value)
                {
                    _book.CurrentPrice = value;
                    OnPropertyChanged("CurrentPrice");
                }
            }
        }
        /// <summary>
        /// Gets or sets the condition.
        /// </summary>
        /// <value>The condition.</value>
        public override Condition Condition
        {
            get
            {
                return _book.Condition;
            }
            set
            {
                if (_book.Condition != value)
                {
                    _book.Condition = value;
                    OnPropertyChanged("Condition");
                }
            }
        }
        /// <summary>
        /// Gets or sets the rating.
        /// </summary>
        /// <value>The rating.</value>
        public override int? Rating
        {
            get
            {
                return _book.Rating;
            }
            set
            {
                if (_book.Rating != value)
                {
                    _book.Rating = value;
                    OnPropertyChanged("Rating");
                }
            }
        }
        /// <summary>
        /// Gets or sets the dedication.
        /// </summary>
        /// <value>The dedication.</value>
        public override string Dedication
        {
            get
            {
                return _book.Dedication;
            }
            set
            {
                if(_book.Dedication != value)
                {
                    _book.Dedication = value;
                    OnPropertyChanged("Dedication");
                }
            }
        }
        /// <summary>
        /// Gets or sets the reading date.
        /// </summary>
        /// <value>The reading date.</value>
        public override DateTime? ReadingDate
        {
            get
            {
                return _book.ReadingDate;
            } 
            set
            {
                if(_book.ReadingDate != value)
                {
                    _book.ReadingDate = value;
                    OnPropertyChanged("ReadingDate");
                }
            }
        }

        /// <summary>
        /// Gets or sets the borrower.
        /// </summary>
        /// <value>The borrower.</value>
        public override Person Borrower
        {
            get
            {
                return _book.Borrower;
            }
            set
            {
                if(_book.Borrower != value)
                {
                    _book.Borrower = value;
                    OnPropertyChanged("Borrower");
                }
            }
        }
        /// <summary>
        /// Gets or sets the borrow date.
        /// </summary>
        /// <value>The borrow date.</value>
        public override DateTime? BorrowDate
        {
            get
            {
                return _book.BorrowDate;
            }
            set
            {
                if(_book.BorrowDate != value)
                {
                    _book.BorrowDate = value;
                    OnPropertyChanged("BorrowDate");
                }
            }
        }

        /// <summary>
        /// Gets or sets the extras.
        /// </summary>
        /// <value>The extras.</value>
        public override ICollection<Extra> Extras
        {
            get
            {
                return _book.Extras;
            }
            set
            {
                if(_book.Extras != value)
                {
                    _book.Extras = value;
                    OnPropertyChanged("Extras");
                }
            }
        }

        /// <summary>
        /// Gets or sets the Library of Congress classification.
        /// </summary>
        /// <value>The lo C classification.</value>
        public override string LoCClassification
        {
            get
            {
                return _book.LoCClassification;
            }
            set
            {
                if(_book.LoCClassification != value)
                {
                    _book.LoCClassification = value;
                    OnPropertyChanged("LoCClassification");
                }
            }
        }
        /// <summary>
        /// Gets or sets the Dewey classification.
        /// </summary>
        /// <value>The dewey classification.</value>
        public override string DeweyClassification
        {
            get
            {
                return _book.DeweyClassification;
            }
            set
            {
                if(_book.DeweyClassification != value)
                {
                    _book.DeweyClassification = value;
                    OnPropertyChanged("DeweyClassification");
                }
            }
        }

        /// <summary>
        /// Gets or sets the other classification.
        /// </summary>
        /// <value>The other classification.</value>
        public override Classification OtherClassification
        {
            get
            {
                return _book.OtherClassification;
            }
            set
            {
                if (_book.OtherClassification != value)
                {
                    _book.OtherClassification = value;
                    OnPropertyChanged("OtherClassification");
                }
            }
        }

        /// <summary>
        /// Gets or sets the copyright.
        /// </summary>
        /// <value>The copyright.</value>
        public override string Copyright
        {

            get
            {
                return _book.Copyright; 
            }
            set
            {
                if (_book.Copyright != value)
                {
                    _book.Copyright = value;
                    OnPropertyChanged("Copyright");
                }
            }

        }
        /// <summary>
        /// Gets or sets the quantity.
        /// </summary>
        /// <value>The quantity.</value>
        public override int? Quantity
        {
            get
            {
                return _book.Quantity;
            } 
            set
            {
                if (_book.Quantity != value)
                {
                    _book.Quantity = value;
                    OnPropertyChanged("Quantity");
                }
            }
        }
        /// <summary>
        /// Gets or sets the location of the document.
        /// </summary>
        /// <value>The location.</value>
        public override string Location
        {
            get
            {
                return _book.Location;
            } 
            set
            {
                if (_book.Location != value)
                {
                    _book.Location = value;
                    OnPropertyChanged("Location");
                }
            }
        }
        /// <summary>
        /// Gets or sets the ISBN number.
        /// </summary>
        /// <value>The ISBN-10.</value>
        public virtual string ISBN
        {
            get
            {
                return _book.ISBN;
            } 
            set
            {
                if (_book.ISBN != value)
                {
                    _book.ISBN = value;
                    OnPropertyChanged("ISBN");
                }
            }
        }

        /// <summary>
        /// Gets a value indicating whether thye entity is a new item.
        /// </summary>
        /// <value>
        /// 	<c>true</c> if the entity is a new item; otherwise, <c>false</c>.
        /// </value>
        protected override bool IsNewItem
        {
            get
            {
                return _book.Id == Guid.Empty;
            }
        }

        /// <summary>
        /// Saves the entity.
        /// </summary>
        public override void Save()
        {
            //if (_book.OtherClassification != null)
            //{
            //    ClassificationRepository classificationRepository = new ClassificationRepository(CurrentData.Current.BookshelfPath);
            //    if(_book.OtherClassification.Id == Guid.Empty)
            //    {
            //        classificationRepository.Add(_book.OtherClassification);
            //    }
            //    else
            //    {
            //        classificationRepository.Update(_book.OtherClassification);
            //    }
            //}

            //if(_book.Cover != null)
            //{
            //    foreach (var cover in _covers)
            //    {
            //        cover.Save();
            //    }
            //}

            IDatabase database = Current.Container.Resolve<IDatabase>();
            using (var unitOfWork = database.CreateUnitOfWork())
            {
                IRepository<Book> repository = new BookRepository(unitOfWork);
                unitOfWork.BeginTransaction();
                try
                {
                    repository.SaveOrUpdate(_book);
                    unitOfWork.CommitTransaction();
                }
                catch
                {
                    unitOfWork.RollbackTransaction();
                }


            }
        }

        /// <summary>
        /// Gets a value indicating whether the entity can be saved.
        /// </summary>
        /// <value><c>true</c> if the entity can be saved; otherwise, <c>false</c>.</value>
        protected override bool CanSave
        {
            get
            {
                return _book.IsValid;
            }
        }



        #region IDataErrorInfo Members

        /// <summary>
        /// Gets an error message indicating what is wrong with this object.
        /// </summary>
        /// <value></value>
        /// <returns>An error message indicating what is wrong with this object. The default is an empty string ("").</returns>
        public override string Error
        {
            get { return (_book as IDataErrorInfo).Error; }
        }

        /// <summary>
        /// Gets the <see cref="System.String"/> with the specified column name.
        /// </summary>
        /// <value></value>
        public override string this[string columnName]
        {
            get 
            {
                string error = string.Empty;
                error = (_book as IDataErrorInfo)[columnName];

                CommandManager.InvalidateRequerySuggested();
                return error;
            }
            
        }

        #endregion

        /// <summary>
        /// Deletes the catalog item.
        /// </summary>
        protected override void Delete()
        {
            IDatabase database = Current.Container.Resolve<IDatabase>();
            using (var unitOfWork = database.CreateUnitOfWork())
            {
                IRepository<Book> repository = new BookRepository(unitOfWork);
                unitOfWork.BeginTransaction();
                try
                {
                    repository.Delete(_book);
                    PublishDeletedItem(this);
                    unitOfWork.CommitTransaction();
                }
                catch
                {
                    unitOfWork.RollbackTransaction();
                }
            }
        }
    }
}